package com.lvt.example.thinking.in.spring.questions.L22.web.example01.url;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * desc：class
 *
 * @author LT
 * @date 2022/10/24
 */
@RestController
public class HelloController {

    /**
     * 案例 1：当 @PathVariable 遇到 /
     * 参考 AbstractHandlerMethodMapping#lookupHandlerMethod
     * @param name
     * @return
     */
    @GetMapping("/hello/{name}")
    public String hello(@PathVariable("name") String name) {
        return name;
    }


    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    /**
     * http://127.0.0.1:8080/hi1/zhagn/san
     * @param request
     * @return  zhagn/san
     */
    @RequestMapping(path = "/hi1/**", method = RequestMethod.GET)
    public String hi1(HttpServletRequest request){
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        //matchPattern 即为"/hi1/**"
        String matchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return antPathMatcher.extractPathWithinPattern(matchPattern, path);
    };


    /**
     * 案例 2：错误使用 @RequestParam、@PathVarible 等注解
     *
     *
     * AbstractNamedValueMethodArgumentResolver#updateNamedValueInfo
     * @param name
     * @return
     */

    @RequestMapping(path = "/hi1", method = RequestMethod.GET)
    public String hi1(@RequestParam("name") String name){
        return name;
    };

    /**
     * 关闭调试参数，上线接口不可用
     <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <configuration>
     <debug>false</debug>
     <parameters>false</parameters>
     </configuration>
     </plugin>

     * @param name
     * @return
     */
    @RequestMapping(path = "/hi2", method = RequestMethod.GET)
    public String hi2(@RequestParam String name){
        return name;
    };


    /**
     * 案例 3：未考虑参数是否可选
     *AbstractNamedValueMethodArgumentResolver#resolveArgument
     *
     * 1. 设置 @RequestParam 的默认值修改代码如下：@RequestParam(value = "address", defaultValue = "no address") String address
     * 2. 设置 @RequestParam 的 required 值 @RequestParam(value = "address", required = false) String address)
     * 3. 标记任何名为 Nullable 且 RetentionPolicy 为 RUNTIME 的注解 @RequestParam(value = "address") @Nullable String address
     * 4、修改参数类型为 Optional @RequestParam(value = "address") Optional address
     */
    @RequestMapping(path = "/hi4", method = RequestMethod.GET)
    public String hi4(@RequestParam("name") String name, @RequestParam("address") String address){
        return name + ":" + address;
    };

    /**
     * 案例 4：请求参数格式错误
     * RequestParamMethodArgumentResolver#resolveName
     *
     * 于案例中的"int age"定义，是需要转化为 int 基本类型的。
     * 这个基本流程可以通过 AbstractNamedValueMethodArgumentResolver#resolveArgument 的关键代码来验证
     *
     * StringToNumberConverterFactory
     */

    @RequestMapping(path = "/hi5", method = RequestMethod.GET)
    public String hi5(@RequestParam("name") String name, @RequestParam("age") int age){
        return name + " is " + age + " years old";
    };


    /**
     * 正确传参方式：http://localhost:8080/hi6?Date=Sat, 12 Aug 1995 13:30:00 GMT
     * 对于 Date 型的 Date 变量，在本案例中，最终找到的是 ObjectToObjectConverter
     *
     * @param date
     * @return
     */
    @RequestMapping(path = "/hi6", method = RequestMethod.GET)
    public String hi6(@RequestParam("Date") Date date){
        return "date is " + date ;
    };

    /**
     * 使用好内置格式转化器
     * 这是因为 AnnotationParserConverter 有目标类型的要求，
     * 这点我们可以通过调试角度来看下，参考 FormattingConversionService#addFormatterForFieldAnnotation 方法的调试试图
     *
     * AnnotationParserConverter#matches
     */
    @RequestMapping(path = "/hi6/fix", method = RequestMethod.GET)
    public String hi6Fix(@RequestParam("Date") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date date){
        return "date is " + date ;
    };
}
